package com.crudpro.javacrud.controller;

import com.crudpro.javacrud.model.ColumnDefinition;
import com.crudpro.javacrud.model.TableDefinition;
import com.crudpro.javacrud.model.TableRenameRequest;
import com.crudpro.javacrud.service.DynamicTableService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/tables")
@RequiredArgsConstructor
@Tag(name = "表格管理", description = "动态表创建、查询、更新和删除操作的API")
@SecurityRequirement(name = "bearerAuth")
public class TableController {

    private final DynamicTableService dynamicTableService;

    @GetMapping
    @Operation(summary = "获取所有表", description = "获取数据库中所有的表名列表")
    @ApiResponse(responseCode = "200", description = "成功获取表列表")
    public ResponseEntity<List<String>> getAllTables() {
        return ResponseEntity.ok(dynamicTableService.getAllTables());
    }

    @PostMapping("/{table}")
    @Operation(summary = "创建新表", description = "使用指定的名称和列定义创建新表")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "201", description = "表创建成功"),
        @ApiResponse(responseCode = "200", description = "表已存在")
    })
    public ResponseEntity<Map<String, String>> createTable(
            @Parameter(description = "表名") @PathVariable String table, 
            @Parameter(description = "列定义") @RequestBody Map<String, ColumnDefinition> columns) {
        // 检查表是否已存在
        List<String> existingTables = dynamicTableService.getAllTables();
        boolean tableExists = existingTables.contains(table);
        
        // 调用创建表方法（实际上使用了IF NOT EXISTS，所以不会重复创建）
        dynamicTableService.createTable(table, columns);
        
        Map<String, String> response = new HashMap<>();
        if (tableExists) {
            // 表已存在
            response.put("message", "Table '" + table + "' already exists");
            return ResponseEntity.ok(response);
        } else {
            // 表成功创建
            response.put("message", "Table '" + table + "' created successfully");
            return new ResponseEntity<>(response, HttpStatus.CREATED);
        }
    }

    @GetMapping("/{table}")
    @Operation(summary = "获取表结构", description = "获取指定表的结构信息，包括所有列的定义")
    @ApiResponse(responseCode = "200", description = "成功获取表结构")
    public ResponseEntity<TableDefinition> getTableStructure(
            @Parameter(description = "表名") @PathVariable String table) {
        return ResponseEntity.ok(dynamicTableService.getTableStructure(table));
    }

    @DeleteMapping("/{table}")
    @Operation(summary = "删除表", description = "删除指定的表")
    @ApiResponse(responseCode = "200", description = "表删除成功")
    public ResponseEntity<Map<String, String>> dropTable(
            @Parameter(description = "表名") @PathVariable String table) {
        dynamicTableService.dropTable(table);
        Map<String, String> response = new HashMap<>();
        response.put("message", "Table '" + table + "' dropped successfully");
        return ResponseEntity.ok(response);
    }

    @PutMapping("/{table}")
    @Operation(summary = "重命名表", description = "将指定的表重命名为新名称")
    @ApiResponse(responseCode = "200", description = "表重命名成功")
    public ResponseEntity<Map<String, String>> renameTable(
            @Parameter(description = "当前表名") @PathVariable String table, 
            @Parameter(description = "新表名") @RequestBody TableRenameRequest request) {
        dynamicTableService.renameTable(table, request.getNewName());
        Map<String, String> response = new HashMap<>();
        response.put("message", "Table '" + table + "' renamed to '" + request.getNewName() + "' successfully");
        return ResponseEntity.ok(response);
    }

    @GetMapping("/{table}/columns")
    public ResponseEntity<Map<String, Object>> getTableColumns(@PathVariable String table) {
        TableDefinition tableDefinition = dynamicTableService.getTableStructure(table);
        Map<String, Object> response = new HashMap<>();
        response.put("table", table);
        response.put("columns", tableDefinition.getColumns());
        return ResponseEntity.ok(response);
    }

    @PostMapping("/{table}/columns")
    public ResponseEntity<Map<String, String>> addColumn(@PathVariable String table, @RequestBody Map<String, ColumnDefinition> columnMap) {
        if (columnMap.size() != 1) {
            Map<String, String> errorResponse = new HashMap<>();
            errorResponse.put("error", "Only one column can be added at a time");
            return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        }
        
        Map.Entry<String, ColumnDefinition> entry = columnMap.entrySet().iterator().next();
        String columnName = entry.getKey();
        ColumnDefinition columnDefinition = entry.getValue();
        
        dynamicTableService.addColumn(table, columnName, columnDefinition);
        
        Map<String, String> response = new HashMap<>();
        response.put("message", "Column '" + columnName + "' added to table '" + table + "' successfully");
        return new ResponseEntity<>(response, HttpStatus.CREATED);
    }

    @PutMapping("/{table}/columns/{column}")
    public ResponseEntity<Map<String, Object>> modifyColumn(
            @PathVariable String table,
            @PathVariable String column,
            @RequestBody Map<String, Object> request) {
        
        String newName = request.containsKey("new_name") ? (String) request.get("new_name") : column;
        
        ColumnDefinition columnDefinition = new ColumnDefinition();
        columnDefinition.setType(request.containsKey("type") ? (String) request.get("type") : "string");
        columnDefinition.setRequired(request.containsKey("required") && (Boolean) request.get("required"));
        columnDefinition.setDefaultValue(request.containsKey("default") ? (String) request.get("default") : null);
        columnDefinition.setComment(request.containsKey("comment") ? (String) request.get("comment") : null);
        
        if (request.containsKey("max_length")) {
            columnDefinition.setMaxLength((Integer) request.get("max_length"));
        }
        
        dynamicTableService.modifyColumn(table, column, newName, columnDefinition);
        
        Map<String, Object> response = new HashMap<>();
        response.put("table", table);
        response.put("old_name", column);
        response.put("new_name", newName);
        response.put("message", "Column '" + column + "' modified successfully");
        
        List<String> changes = new java.util.ArrayList<>();
        changes.add("CHANGE COLUMN " + column + " " + newName);
        
        if (request.containsKey("type")) {
            changes.add("MODIFY COLUMN " + column + " " + request.get("type").toString().toUpperCase());
        }
        
        if (request.containsKey("required")) {
            changes.add("MODIFY COLUMN " + column + " SET " + (((Boolean) request.get("required")) ? "NOT NULL" : "NULL"));
        }
        
        if (request.containsKey("default")) {
            changes.add("MODIFY COLUMN " + column + " SET DEFAULT '" + request.get("default") + "'");
        }
        
        if (request.containsKey("comment")) {
            changes.add("MODIFY COLUMN " + column + " COMMENT '" + request.get("comment") + "'");
        }
        
        response.put("changes", changes);
        
        return ResponseEntity.ok(response);
    }

    @DeleteMapping("/{table}/columns/{column}")
    public ResponseEntity<Map<String, String>> dropColumn(@PathVariable String table, @PathVariable String column) {
        dynamicTableService.dropColumn(table, column);
        Map<String, String> response = new HashMap<>();
        response.put("message", "Column '" + column + "' dropped from table '" + table + "' successfully");
        return ResponseEntity.ok(response);
    }

    @PostMapping("/{table}/records")
    @Operation(summary = "添加记录", description = "向指定表中添加一条新记录")
    @ApiResponse(responseCode = "201", description = "记录添加成功")
    public ResponseEntity<Map<String, Object>> insertRecord(
            @Parameter(description = "表名") @PathVariable String table, 
            @Parameter(description = "记录数据") @RequestBody Map<String, Object> record) {
        Map<String, Object> insertedRecord = dynamicTableService.insertRecord(table, record);
        return new ResponseEntity<>(insertedRecord, HttpStatus.CREATED);
    }

    @GetMapping("/{table}/records")
    @Operation(summary = "获取所有记录", description = "获取指定表中的所有记录")
    @ApiResponse(responseCode = "200", description = "成功获取记录列表")
    public ResponseEntity<List<Map<String, Object>>> getAllRecords(
            @Parameter(description = "表名") @PathVariable String table) {
        return ResponseEntity.ok(dynamicTableService.getAllRecords(table));
    }

    @GetMapping("/{table}/records/{id}")
    public ResponseEntity<Map<String, Object>> getRecordById(@PathVariable String table, @PathVariable Long id) {
        Map<String, Object> record = dynamicTableService.getRecordById(table, id);
        if (record == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(record);
    }

    @PutMapping("/{table}/records/{id}")
    public ResponseEntity<Map<String, Object>> updateRecord(
            @PathVariable String table,
            @PathVariable Long id,
            @RequestBody Map<String, Object> record) {
        
        Map<String, Object> existingRecord = dynamicTableService.getRecordById(table, id);
        if (existingRecord == null) {
            return ResponseEntity.notFound().build();
        }
        
        Map<String, Object> updatedRecord = dynamicTableService.updateRecord(table, id, record);
        return ResponseEntity.ok(updatedRecord);
    }

    @DeleteMapping("/{table}/records/{id}")
    public ResponseEntity<Map<String, String>> deleteRecord(@PathVariable String table, @PathVariable Long id) {
        Map<String, Object> existingRecord = dynamicTableService.getRecordById(table, id);
        if (existingRecord == null) {
            return ResponseEntity.notFound().build();
        }
        
        dynamicTableService.deleteRecord(table, id);
        
        Map<String, String> response = new HashMap<>();
        response.put("message", "Record with ID " + id + " deleted from table '" + table + "' successfully");
        return ResponseEntity.ok(response);
    }
} 